package com.rickpan.entity;

import jakarta.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.List;

/**
 * 上传会话实体
 * 用于管理分片上传的会话状态
 */
@Entity
@Table(name = "upload_sessions")
public class UploadSession {
    
    @Id
    @Column(length = 64)
    private String id;
    
    @Column(name = "user_id", nullable = false)
    private Long userId;
    
    @Column(name = "file_name", nullable = false)
    private String fileName;
    
    @Column(name = "file_size", nullable = false)
    private Long fileSize;
    
    @Column(name = "file_sha256", length = 64, nullable = false)
    private String fileSha256;
    
    @Column(name = "chunk_size", nullable = false)
    private Integer chunkSize;
    
    @Column(name = "total_chunks", nullable = false)
    private Integer totalChunks;
    
    @Column(name = "uploaded_chunks", columnDefinition = "TEXT")
    private String uploadedChunks; // JSON数组格式存储已上传分片
    
    @Column(name = "parent_id")
    private Long parentId;
    
    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private UploadStatus status = UploadStatus.UPLOADING;
    
    @Column(name = "created_at", nullable = false)
    private LocalDateTime createdAt;
    
    @Column(name = "expires_at", nullable = false)
    private LocalDateTime expiresAt;
    
    // 关联用户
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", insertable = false, updatable = false)
    private User user;
    
    // 关联父目录
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id", insertable = false, updatable = false)
    private FileInfo parentFolder;
    
    /**
     * 上传状态枚举
     */
    public enum UploadStatus {
        UPLOADING,  // 上传中
        COMPLETED,  // 已完成
        FAILED,     // 失败
        EXPIRED     // 已过期
    }
    
    // 构造函数
    public UploadSession() {
        this.createdAt = LocalDateTime.now();
        // 默认24小时过期
        this.expiresAt = LocalDateTime.now().plusHours(24);
    }
    
    public UploadSession(String id, Long userId, String fileName, Long fileSize, 
                        String fileSha256, Integer chunkSize, Integer totalChunks) {
        this();
        this.id = id;
        this.userId = userId;
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.fileSha256 = fileSha256;
        this.chunkSize = chunkSize;
        this.totalChunks = totalChunks;
        this.uploadedChunks = "[]"; // 初始化为空数组
    }
    
    // Getter和Setter方法
    public String getId() {
        return id;
    }
    
    public void setId(String id) {
        this.id = id;
    }
    
    public Long getUserId() {
        return userId;
    }
    
    public void setUserId(Long userId) {
        this.userId = userId;
    }
    
    public String getFileName() {
        return fileName;
    }
    
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
    
    public Long getFileSize() {
        return fileSize;
    }
    
    public void setFileSize(Long fileSize) {
        this.fileSize = fileSize;
    }
    
    public String getFileSha256() {
        return fileSha256;
    }
    
    public void setFileSha256(String fileSha256) {
        this.fileSha256 = fileSha256;
    }
    
    public Integer getChunkSize() {
        return chunkSize;
    }
    
    public void setChunkSize(Integer chunkSize) {
        this.chunkSize = chunkSize;
    }
    
    public Integer getTotalChunks() {
        return totalChunks;
    }
    
    public void setTotalChunks(Integer totalChunks) {
        this.totalChunks = totalChunks;
    }
    
    public String getUploadedChunks() {
        return uploadedChunks;
    }
    
    public void setUploadedChunks(String uploadedChunks) {
        this.uploadedChunks = uploadedChunks;
    }
    
    public Long getParentId() {
        return parentId;
    }
    
    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }
    
    public UploadStatus getStatus() {
        return status;
    }
    
    public void setStatus(UploadStatus status) {
        this.status = status;
    }
    
    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
    
    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }
    
    public LocalDateTime getExpiresAt() {
        return expiresAt;
    }
    
    public void setExpiresAt(LocalDateTime expiresAt) {
        this.expiresAt = expiresAt;
    }
    
    public User getUser() {
        return user;
    }
    
    public void setUser(User user) {
        this.user = user;
    }
    
    public FileInfo getParentFolder() {
        return parentFolder;
    }
    
    public void setParentFolder(FileInfo parentFolder) {
        this.parentFolder = parentFolder;
    }
    
    /**
     * 检查会话是否过期
     */
    public boolean isExpired() {
        return LocalDateTime.now().isAfter(this.expiresAt);
    }
    
    /**
     * 检查是否可以上传
     */
    public boolean canUpload() {
        return this.status == UploadStatus.UPLOADING && !isExpired();
    }
    
    /**
     * 标记为已完成
     */
    public void markCompleted() {
        this.status = UploadStatus.COMPLETED;
    }
    
    /**
     * 标记为失败
     */
    public void markFailed() {
        this.status = UploadStatus.FAILED;
    }
    
    /**
     * 标记为过期
     */
    public void markExpired() {
        this.status = UploadStatus.EXPIRED;
    }

    /**
     * 解析已上传分片列表
     */
    public List<Integer> parseUploadedChunks() {
        if (uploadedChunks == null || uploadedChunks.equals("[]")) {
            return new ArrayList<>();
        }

        try {
            // 简单的JSON数组解析
            String chunksStr = uploadedChunks.trim();
            if (chunksStr.startsWith("[") && chunksStr.endsWith("]")) {
                chunksStr = chunksStr.substring(1, chunksStr.length() - 1);
                if (chunksStr.isEmpty()) {
                    return new ArrayList<>();
                }

                List<Integer> chunks = new ArrayList<>();
                String[] parts = chunksStr.split(",");
                for (String part : parts) {
                    chunks.add(Integer.parseInt(part.trim()));
                }
                return chunks;
            }
        } catch (Exception e) {
            // 解析失败，返回空列表
        }

        return new ArrayList<>();
    }

    /**
     * 计算已上传字节数（标准算法）
     */
    public long calculateUploadedBytes() {
        List<Integer> chunks = parseUploadedChunks();
        if (chunks.isEmpty()) {
            return 0L;
        }

        long uploadedBytes = (long) chunks.size() * chunkSize;

        // 调整最后一个分片的大小
        if (chunks.contains(totalChunks - 1)) {
            long lastChunkSize = fileSize % chunkSize;
            if (lastChunkSize > 0) {
                uploadedBytes = uploadedBytes - chunkSize + lastChunkSize;
            }
        }

        return uploadedBytes;
    }

    /**
     * 计算上传进度百分比
     */
    public int calculateProgress() {
        if (fileSize == 0) {
            return 0;
        }

        long uploadedBytes = calculateUploadedBytes();
        return Math.min(100, (int) Math.round((double) uploadedBytes / fileSize * 100));
    }
    
    @Override
    public String toString() {
        return "UploadSession{" +
                "id='" + id + '\'' +
                ", userId=" + userId +
                ", fileName='" + fileName + '\'' +
                ", fileSize=" + fileSize +
                ", status=" + status +
                ", createdAt=" + createdAt +
                ", expiresAt=" + expiresAt +
                '}';
    }
}
